﻿// The following code is inspired by the work of Josh Smith
// http://joshsmithonwpf.wordpress.com/
using System;
using System.Diagnostics;
using System.Windows.Input;

namespace Shazzam.Commands
{
  /// <summary>
  /// A command whose sole purpose is to
  /// relay its functionality to other
  /// objects by invoking delegates. The
  /// default return value for the CanExecute
  /// method is 'true'.
  /// </summary>
  public class RelayCommand<T> : ICommand
  {
    #region Constructors

    public RelayCommand(Action<T> execute)
      : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<T> execute, Predicate<T> canExecute)
    {
      if (execute == null)
        throw new ArgumentNullException("execute");

      _execute = execute;
      _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
      return _canExecute == null ? true : _canExecute((T)parameter);
    }

    public event EventHandler CanExecuteChanged
    {
      add
      {
        if (_canExecute != null)
          CommandManager.RequerySuggested += value;
      }
      remove
      {
        if (_canExecute != null)
          CommandManager.RequerySuggested -= value;
      }
    }

    public void Execute(object parameter)
    {
      _execute((T)parameter);
    }

    #endregion // ICommand Members

    #region Fields

    readonly Action<T> _execute = null;
    readonly Predicate<T> _canExecute = null;

    #endregion // Fields
  }

  /// <summary>
  /// A command whose sole purpose is to
  /// relay its functionality to other
  /// objects by invoking delegates. The
  /// default return value for the CanExecute
  /// method is 'true'.
  /// </summary>
  public class RelayCommand : ICommand
  {
    #region Constructors

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action execute)
      : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action execute, Func<bool> canExecute)
    {
      if (execute == null)
        throw new ArgumentNullException("execute");

      _execute = execute;
      _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
      return _canExecute == null ? true : _canExecute();
    }

    public event EventHandler CanExecuteChanged
    {
      add
      {
        if (_canExecute != null)
          CommandManager.RequerySuggested += value;
      }
      remove
      {
        if (_canExecute != null)
          CommandManager.RequerySuggested -= value;
      }
    }

    public void Execute(object parameter)
    {
      _execute();
    }

    #endregion // ICommand Members

    #region Fields

    readonly Action _execute;
    readonly Func<bool> _canExecute;

    #endregion // Fields
  }
}
